#include "server.h"

ubus_server::ubus_server(const char * filename){
	init_server(filename);
	FD_SET(this->serverfd, &readfds);
	maxfd = this->serverfd;
}

ubus_server::~ubus_server() {

}

void ubus_server::init_server(const char *filename) {
	int size;
	unlink(filename);
    this->serverfd = socket(AF_UNIX, SOCK_STREAM|SOCK_NONBLOCK, 0);
    if ( this->serverfd < 0) {  
        printf("socket failed\n");  
        exit(1);  
    }

	memset(&server_un, 0, sizeof(server_un));
    server_un.sun_family = AF_UNIX;  
    strcpy(server_un.sun_path, filename);
    size = offsetof(struct sockaddr_un, sun_path) + strlen(server_un.sun_path);  
  
    if (bind(this->serverfd, (struct sockaddr *)&server_un, size) < 0) {  
        perror("bind error");  
        exit(1);  
    }  

	if (listen(this->serverfd, 20) < 0) {  
        perror("listen error");  
        exit(1);          
    }
}


void ubus_server::start() {

	while(1) {

		fd_set tmpfds = readfds;
		int ret = select(maxfd+1,&tmpfds,NULL,NULL,NULL);

		if(ret < 0) {
			perror("select error\n");
			break;
		}

		if(ret == 0) {
			printf("select timeout!\n");
		}

		for (int eventfd=0; eventfd<=maxfd; eventfd++) {

			if (FD_ISSET(eventfd,&tmpfds)<=0) continue;

			if(eventfd == this->serverfd) {
				struct sockaddr_un client;
				socklen_t len = sizeof(client);
				int clientsock = ::accept4(this->serverfd, (struct sockaddr*)&client, &len, SOCK_NONBLOCK);
				//int clientsock = accept(this->serverfd, (struct sockaddr*)&client, &len);
				if(clientsock < 0) {
					printf("accept() failed.\n");
					continue;
				}

				FD_SET(clientsock,&readfds);

				if(clientsock > maxfd) maxfd = clientsock;
				continue;
			} else {
				char buffer[512] = {0};
				std::string ss;
				while(1)
				{	
					memset(buffer,0,sizeof(buffer));
					int nread = read(eventfd, buffer, sizeof(buffer));
					if (nread > 0) {
						buf_.append(buffer, nread);
					}else if (nread == -1 && errno == EINTR ) {
						
						continue;
					}else if (nread == -1 && ((errno == EAGAIN) || (errno == EWOULDBLOCK))) {
						
						while(1)
						{	
							int len = 0;
							memcpy(&len, buf_.c_str(), 4);
							if(buf_.size() < len + 4)
							{
								break;
							}
							ss = buf_.substr(4,len);
							buf_.erase(0,len + 4);
							this -> handleMessage(eventfd,ss);
						}
						break;
					}else if (nread == 0) {
						close(eventfd);
						FD_CLR(eventfd,&readfds);
						if(eventfd == maxfd) {
							for (int ii=maxfd; ii>0; ii--) {
								if(FD_ISSET(ii,&readfds)) {
									maxfd = ii;
									break;
								}
							}
						}
						break;
					}
				}
				
			}
			
			
			}
		}
}


void ubus_server::handleMessage(int eventfd, std::string &message)
{	
/*
typedef struct message{
	head head_;
	char content[255];
}message;

typedef struct head{
	int type;
	int len;
}head;


*/
	std::thread th1([eventfd,&message]()->void{
		message_ *pmessage = reinterpret_cast<message_*>(message.data());
		printf("%d , %d , %s\n", pmessage->head_.type, pmessage->head_.len ,pmessage->content);
		write(eventfd, message.c_str(), message.size());
	});
	th1.join();
}



